{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--NAVIGATION-->\n",
    "< [比较，遮盖和布尔逻辑](02.06-Boolean-Arrays-and-Masks.ipynb) | [目录](Index.ipynb) | [数组排序](02.08-Sorting.ipynb) >\n",
    "\n",
    "<a href=\"https://colab.research.google.com/github/wangyingsm/Python-Data-Science-Handbook/blob/master/notebooks/02.07-Fancy-Indexing.ipynb\"><img align=\"left\" src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open in Colab\" title=\"Open and Execute in Google Colaboratory\"></a>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fancy Indexing\n",
    "\n",
    "# 高级索引"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> In the previous sections, we saw how to access and modify portions of arrays using simple indices (e.g., ``arr[0]``), slices (e.g., ``arr[:5]``), and Boolean masks (e.g., ``arr[arr > 0]``).\n",
    "In this section, we'll look at another style of array indexing, known as *fancy indexing*.\n",
    "Fancy indexing is like the simple indexing we've already seen, but we pass arrays of indices in place of single scalars.\n",
    "This allows us to very quickly access and modify complicated subsets of an array's values.\n",
    "\n",
    "在前面的小节中，我们学习了如何获取和修改数组的元素或部分元素，我们可以通过简单索引（例如`arr[0]`），切片（例如`arr[:5]`）和布尔遮盖（例如`arr[arr > 0]`）来实现。本节来介绍另外一种数组索引的方式，被称为*高级索引*。高级索引语法上和前面我们学习到的简单索引很像，区别只是它不是传递标量参数作为索引值，而是传递数组参数作为索引值。它能让我们很迅速的获取和修改复杂数组或子数组的元素值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exploring Fancy Indexing\n",
    "\n",
    "## 初探高级索引\n",
    "\n",
    "> Fancy indexing is conceptually simple: it means passing an array of indices to access multiple array elements at once.\n",
    "For example, consider the following array:\n",
    "\n",
    "高级索引在概念层面非常简单：传递一个数组作为索引值参数，使得用户能一次性的获取或修改多个数组元素值。例如下面的数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[51 92 14 71 60 20 82 86 74 74]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "rand = np.random.RandomState(42)\n",
    "\n",
    "x = rand.randint(100, size=10)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Suppose we want to access three different elements. We could do it like this:\n",
    "\n",
    "假如我们需要访问其中三个不同的元素。我们可以这样做："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[71, 86, 14]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x[3], x[7], x[2]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Alternatively, we can pass a single list or array of indices to obtain the same result:\n",
    "\n",
    "还有一种方法，我们以一个数组的方式将这些元素的索引传递给数组，也可以获得相同的结果："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([71, 86, 60])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ind = [3, 7, 4]\n",
    "x[ind]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> When using fancy indexing, the shape of the result reflects the shape of the *index arrays* rather than the shape of the *array being indexed*:\n",
    "\n",
    "当使用高级索引时，结果数组的形状取决于*索引数组*的形状而不是*被索引数组*的形状："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[71, 86],\n",
       "       [60, 20]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ind = np.array([[3, 7],\n",
    "                [4, 5]]) # 索引数组是一个2x2数组，结果也将会是一个2x2数组\n",
    "x[ind]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Fancy indexing also works in multiple dimensions. Consider the following array:\n",
    "\n",
    "高级索引也支持多维数组。例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = np.arange(12).reshape((3, 4))\n",
    "X"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Like with standard indexing, the first index refers to the row, and the second to the column:\n",
    "\n",
    "就像普通索引一样，第一个参数代表行，第二个参数代表列："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 2,  5, 11])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "row = np.array([0, 1, 2])\n",
    "col = np.array([2, 1, 3])\n",
    "X[row, col]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Notice that the first value in the result is ``X[0, 2]``, the second is ``X[1, 1]``, and the third is ``X[2, 3]``.\n",
    "The pairing of indices in fancy indexing follows all the broadcasting rules that were mentioned in [Computation on Arrays: Broadcasting](02.05-Computation-on-arrays-broadcasting.ipynb).\n",
    "So, for example, if we combine a column vector and a row vector within the indices, we get a two-dimensional result:\n",
    "\n",
    "结果中的第一个值是`x[0, 2]`，第二个值是`x[1, 1]`，第三个值是`x[2, 3]`。高级索引的多个维度组合方式也遵守广播的规则，请查阅[在数组上计算：广播](02.05-Computation-on-arrays-broadcasting.ipynb)。因此，如果我们在上面的行索引数组中增加一个维度，结果将变成一个二维数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2,  1,  3],\n",
       "       [ 6,  5,  7],\n",
       "       [10,  9, 11]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[row[:, np.newaxis], col]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Here, each row value is matched with each column vector, exactly as we saw in broadcasting of arithmetic operations.\n",
    "For example:\n",
    "\n",
    "这里，每个行索引都会匹配每个列的向量，就像我们在广播的算术运算中看到一样。例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0],\n",
       "       [2, 1, 3],\n",
       "       [4, 2, 6]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "row[:, np.newaxis] * col"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> It is always important to remember with fancy indexing that the return value reflects the *broadcasted shape of the indices*, rather than the shape of the array being indexed.\n",
    "\n",
    "记住高级索引结果的形状是*索引数组广播后的形状*而不是被索引数组形状，这点非常重要。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Combined Indexing\n",
    "\n",
    "## 组合索引\n",
    "\n",
    "> For even more powerful operations, fancy indexing can be combined with the other indexing schemes we've seen:\n",
    "\n",
    "结合我们前面学习过的索引方法，我们可以组合出更多更强大的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]]\n"
     ]
    }
   ],
   "source": [
    "print(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> We can combine fancy and simple indices:\n",
    "\n",
    "我们可以将高级索引和简单索引进行组合：\n",
    "\n",
    "译者注，实际上这就是个广播，将标量广播成一个向量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([10,  8,  9])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[2, [2, 0, 1]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> We can also combine fancy indexing with slicing:\n",
    "\n",
    "我们也可以将高级索引和切片进行组合："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 6,  4,  5],\n",
       "       [10,  8,  9]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[1:, [2, 0, 1]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> And we can combine fancy indexing with masking:\n",
    "\n",
    "还可以将高级索引和遮盖进行组合："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  2],\n",
       "       [ 4,  6],\n",
       "       [ 8, 10]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mask = np.array([1, 0, 1, 0], dtype=bool)\n",
    "X[row[:, np.newaxis], mask]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> All of these indexing options combined lead to a very flexible set of operations for accessing and modifying array values.\n",
    "\n",
    "所有这些索引操作可以提供用户非常灵活的方式来获取和修改数组中的数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example: Selecting Random Points\n",
    "\n",
    "## 例子：选择随机点\n",
    "\n",
    "> One common use of fancy indexing is the selection of subsets of rows from a matrix.\n",
    "For example, we might have an $N$ by $D$ matrix representing $N$ points in $D$ dimensions, such as the following points drawn from a two-dimensional normal distribution:\n",
    "\n",
    "高级索引的一个通用应用场景就是从一个矩阵的行中选取子数据集。例如，我们有一个$N \\times D$的矩阵，代表着一个$D$维平面上有$N$个点，例如下面的二维正态分布的点集合："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(100, 2)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mean = [0, 0]\n",
    "cov = [[1, 2],\n",
    "       [2, 5]]\n",
    "X = rand.multivariate_normal(mean, cov, 100)\n",
    "X.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Using the plotting tools we will discuss in [Introduction to Matplotlib](04.00-Introduction-To-Matplotlib.ipynb), we can visualize these points as a scatter-plot:\n",
    "\n",
    "使用我们会在[第四章](04.00-Introduction-To-Matplotlib.ipynb)详细介绍的Matplotlib工具，我们可以在散点图上绘制这些点："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn; seaborn.set()  # 设置图表风格，seaborn\n",
    "\n",
    "plt.scatter(X[:, 0], X[:, 1]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Let's use fancy indexing to select 20 random points. We'll do this by first choosing 20 random indices with no repeats, and use these indices to select a portion of the original array:\n",
    "\n",
    "下面我们使用高级索引来选择20个随机点。方法是先创建一个索引数组，里面的索引值是没有重复的，然后使用这个索引数组来选择点："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([42, 64, 11, 76, 46, 33, 77, 14, 91, 20, 13,  4, 60, 49,  0, 32, 21,\n",
       "       55, 40, 61])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "indices = np.random.choice(X.shape[0], 20, replace=False)\n",
    "indices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(20, 2)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "selection = X[indices]  # 使用高级索引\n",
    "selection.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Now to see which points were selected, let's over-plot large circles at the locations of the selected points:\n",
    "\n",
    "下面我们来看看那些点被选中，让我们上图的基础上将选中的点圈出来："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(X[:, 0], X[:, 1], alpha=0.3)\n",
    "plt.scatter(selection[:, 0], selection[:, 1],\n",
    "            facecolor='none', s=200);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> This sort of strategy is often used to quickly partition datasets, as is often needed in train/test splitting for validation of statistical models (see [Hyperparameters and Model Validation](05.03-Hyperparameters-and-Model-Validation.ipynb)), and in sampling approaches to answering statistical questions.\n",
    "\n",
    "这种策略经常用来划分数据集，比如用来验证统计模型正确性时需要的训练集和测试集划分（参见[超参数及模型验证](05.03-Hyperparameters-and-Model-Validation.ipynb)），还有就是在回答统计问题时进行取样抽象。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Modifying Values with Fancy Indexing\n",
    "\n",
    "## 使用高级索引修改数据\n",
    "\n",
    "> Just as fancy indexing can be used to access parts of an array, it can also be used to modify parts of an array.\n",
    "For example, imagine we have an array of indices and we'd like to set the corresponding items in an array to some value:\n",
    "\n",
    "前面我们看到高级索引能够被用来获取一个数组的部分数据，实际上它还能用来修改选中部分的数据。例如，我们手头有一个索引的数组，我们想将这些索引上的数据修改为某个值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0 99 99  3 99  5  6  7 99  9]\n"
     ]
    }
   ],
   "source": [
    "x = np.arange(10)\n",
    "i = np.array([2, 1, 8, 4])\n",
    "x[i] = 99\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> We can use any assignment-type operator for this. For example:\n",
    "\n",
    "我们可以使用任何赋值类型操作，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0 89 89  3 89  5  6  7 89  9]\n"
     ]
    }
   ],
   "source": [
    "x[i] -= 10\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Notice, though, that repeated indices with these operations can cause some potentially unexpected results. Consider the following:\n",
    "\n",
    "请注意下，如果索引数组中有重复的元素的话，这种修改操作可能会导致一个潜在的意料之外的结果。例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[6. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n"
     ]
    }
   ],
   "source": [
    "x = np.zeros(10)\n",
    "x[[0, 0]] = [4, 6]\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Where did the 4 go? The result of this operation is to first assign ``x[0] = 4``, followed by ``x[0] = 6``.\n",
    "The result, of course, is that ``x[0]`` contains the value 6.\n",
    "\n",
    "4跑到哪里去了呢？这个操作首先赋值`x[0] = 4`，然后赋值`x[0] = 6`，因此最后`x[0]`的值是6。\n",
    "\n",
    "> Fair enough, but consider this operation:\n",
    "\n",
    "上面的例子还算比较清晰，再看下面这个操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6., 0., 1., 1., 1., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "i = [2, 3, 3, 4, 4, 4]\n",
    "x[i] += 1\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> You might expect that ``x[3]`` would contain the value 2, and ``x[4]`` would contain the value 3, as this is how many times each index is repeated. Why is this not the case?\n",
    "Conceptually, this is because ``x[i] += 1`` is meant as a shorthand of ``x[i] = x[i] + 1``. ``x[i] + 1`` is evaluated, and then the result is assigned to the indices in x.\n",
    "With this in mind, it is not the augmentation that happens multiple times, but the assignment, which leads to the rather nonintuitive results.\n",
    "\n",
    "> So what if you want the other behavior where the operation is repeated? For this, you can use the ``at()`` method of ufuncs (available since NumPy 1.8), and do the following:\n",
    "\n",
    "我们期望的结果可能是`x[3]`的值是2，而`x[4]`的值是3，因为这两个元素都多次执行了加法操作。但是为何结果不是呢？这是因为`x[i] += 1`是操作`x[i] = x[i] + 1`的简写，而`x[i] + 1`表达式的值已经计算好了，然后才被赋值给`x[i]`。因此，上面的操作不会被扩展为重复的运算，而是一次的赋值操作，造成了这种难以理解的结果。\n",
    "\n",
    "如果我们真的需要这种重复的操作怎么办？对此，NumPy（版本1.8以上）提供了`at()`ufunc方法可以满足这个目的，如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0. 0. 1. 2. 3. 0. 0. 0. 0. 0.]\n"
     ]
    }
   ],
   "source": [
    "x = np.zeros(10)\n",
    "np.add.at(x, i, 1)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> The ``at()`` method does an in-place application of the given operator at the specified indices (here, ``i``) with the specified value (here, 1).\n",
    "Another method that is similar in spirit is the ``reduceat()`` method of ufuncs, which you can read about in the NumPy documentation.\n",
    "\n",
    "`at()`方法不会预先计算表达式的值，而是每次运算时实时得到，方法在一个数组`x`中取得特定索引`i`，然后将其取得的值与最后一个参数`1`进行相应计算，这里是加法`add`。还有一个类似的方法是`reduceat()`方法，你可以从NumPy的文档中阅读它的说明。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example: Binning Data\n",
    "\n",
    "## 例子：数据分组\n",
    "\n",
    "> You can use these ideas to efficiently bin data to create a histogram by hand.\n",
    "For example, imagine we have 1,000 values and would like to quickly find where they fall within an array of bins.\n",
    "We could compute it using ``ufunc.at`` like this:\n",
    "\n",
    "你可以使用上面的方法对数据进行高效分组，用于定义自己的直方图。例如，设想我们有1000个值，我们想将它们分别放入各个不同的数组分组中。我们可以使用`at`函数，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(42)\n",
    "x = np.random.randn(100) # 获得一个一维100个标准正态分布值\n",
    "\n",
    "# 得到一个自定义的数据分组，区间-5至5平均取20个点，每个区间为一个数据分组\n",
    "bins = np.linspace(-5, 5, 20)\n",
    "counts = np.zeros_like(bins) # counts是x数值落入区间的计数\n",
    "\n",
    "# 使用searchsorted，得到x每个元素在bins中落入的区间序号\n",
    "i = np.searchsorted(bins, x)\n",
    "\n",
    "# 使用at和add，对x元素在每个区间的元素个数进行计算\n",
    "np.add.at(counts, i, 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> The counts now reflect the number of points within each bin–in other words, a histogram:\n",
    "\n",
    "counts现在包含着每个数据分组中元素的个数，换句话来说，就是直方图：\n",
    "\n",
    "译者注：Matplotlib 3.1开始，linestyle关键字参数已经过时，后续版本会抛弃。下面代码依据最新参数更改为drawstyle或ds。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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g4Navny5+vr6nB4rK65cuaJLly6poqLC6VHShqAn6YMPPtD27du1bJkzN6vOto0bN6qwsFCSVFtbqzt37igWizk8VXqFw2GNjIyoublZktTc3KyRkRHTO9bi4mLV19c/+u/a2lrdvn3bwYmyY3p6Wj09Peru7nZ6lLQi6En4/vvvNTU1pc2bNzs9iiP6+/vV0NAgl8vWb59gMKjy8nK53W5JktvtVllZmYLBoMOTZUcsFtOJEyfU2Njo9CgZ9+mnn2rLli2qrKx0epS0cvzjc3PRK6+8MuMu5cyZMzpw4ICOHTuW5akya7Y1//DDD48id+rUKQ0ODqq/vz+b4yELent7tXjxYrW1tTk9Skb99NNPunz5strb250eJe0I+lN89dVXMz534cIFTUxM6NVXX5X08B+Vvv32W92/f187d+7M1ohpN9ua/3Du3Dl98sknOn78uJ555pksTJVdPp9P4+PjikajcrvdikajCoVC8vl8To+WcYFAQDdv3tSRI0fM/c3rcT/++KN++eUXbdq0SZJ0584dbd++Xe+//75eeuklh6dLURwp2bNnT/zzzz93eoyM++abb+IbN26Mj46OOj1KRrW1tcUHBgbi8Xg8PjAwEG9ra3N4osw7cOBAvK2tLf7gwQOnR3HExo0b41evXnV6jLRgh455effdd1VYWKg333zz0WPHjx8394/C3d3d2rt3rw4fPqyioiIFAgGnR8qo69ev6+jRo1q1apVaW1slSZWVlTp06JDDkyEZ3LEIAIywfbIMABYQgg4ARhB0ADCCoAOAEQQdAIwg6ABgBEEHACMIOgAY8f9Zq7o+lLCCQAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 用图表展示结果\n",
    "plt.plot(bins, counts, ds='steps');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Of course, it would be silly to have to do this each time you want to plot a histogram.\n",
    "This is why Matplotlib provides the ``plt.hist()`` routine, which does the same in a single line:\n",
    "\n",
    "当然，如果每次要画直方图的时候，都要经过这么复杂的计算，很不方便。这也就是为什么Matplotlib提供了`plt.hist()`方法的原因，可以用一行代码完成上面操作：\n",
    "\n",
    "```python\n",
    "plt.hist(x, bins, histtype='step');\n",
    "```\n",
    "\n",
    "> This function will create a nearly identical plot to the one seen here.\n",
    "To compute the binning, ``matplotlib`` uses the ``np.histogram`` function, which does a very similar computation to what we did before. Let's compare the two here:\n",
    "\n",
    "这个函数会创建一个和上图基本完全一样的图形。Matplotlib使用`np.histogram`函数来计算数据分组，这个函数进行的计算和我们上面的代码非常接近。我们比较一下这两个方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NumPy routine:\n",
      "22.7 µs ± 1.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n",
      "Custom routine:\n",
      "12.1 µs ± 426 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "print(\"NumPy routine:\")\n",
    "%timeit counts, edges = np.histogram(x, bins)\n",
    "\n",
    "print(\"Custom routine:\")\n",
    "%timeit np.add.at(counts, np.searchsorted(bins, x), 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Our own one-line algorithm is several times faster than the optimized algorithm in NumPy! How can this be?\n",
    "If you dig into the ``np.histogram`` source code (you can do this in IPython by typing ``np.histogram??``), you'll see that it's quite a bit more involved than the simple search-and-count that we've done; this is because NumPy's algorithm is more flexible, and particularly is designed for better performance when the number of data points becomes large:\n",
    "\n",
    "我们自己写的一行代码比NumPy优化的算法要快出许多，这是因为什么？如果你深入到`np.histogram`函数的源代码进行阅读（你可以通过在IPython中输入`np.histogram??`来查阅）的时候，你会发现函数除了搜索和计数之外，还做了其他很多工作；这是因为NumPy的函数要更加灵活，而且当数据量变大的时候能够提供更好的性能："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NumPy routine:\n",
      "67.2 ms ± 1.62 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
      "Custom routine:\n",
      "90.4 ms ± 1.62 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "x = np.random.randn(1000000)\n",
    "print(\"NumPy routine:\")\n",
    "%timeit counts, edges = np.histogram(x, bins)\n",
    "\n",
    "print(\"Custom routine:\")\n",
    "%timeit np.add.at(counts, np.searchsorted(bins, x), 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> What this comparison shows is that algorithmic efficiency is almost never a simple question. An algorithm efficient for large datasets will not always be the best choice for small datasets, and vice versa (see [Big-O Notation](02.08-Sorting.ipynb#Aside:-Big-O-Notation)).\n",
    "But the advantage of coding this algorithm yourself is that with an understanding of these basic methods, you could use these building blocks to extend this to do some very interesting custom behaviors.\n",
    "The key to efficiently using Python in data-intensive applications is knowing about general convenience routines like ``np.histogram`` and when they're appropriate, but also knowing how to make use of lower-level functionality when you need more pointed behavior.\n",
    "\n",
    "上面的结果说明当涉及到算法的性能时，永远不可能是一个简单的问题。对于大数据集来说一个很高效的算法，并不一定也适用于小数据集，反之亦然（参见[大O复杂度](02.08-Sorting.ipynb#Aside:-Big-O-Notation)）。我们这里使用自己的代码实现这个算法，目的是理解上面的基本函数，后续读者可以使用这些函数构建自己定义的各种功能。在数据科学应用中使用Python编写代码的关键在于，你能掌握NumPy提供的很方便的函数如`np.histogram`，你也能知道什么情况下适合使用它们，当需要更加定制的功能时你还能使用底层的函数自己实现相应的算法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--NAVIGATION-->\n",
    "< [比较，遮盖和布尔逻辑](02.06-Boolean-Arrays-and-Masks.ipynb) | [目录](Index.ipynb) | [数组排序](02.08-Sorting.ipynb) >\n",
    "\n",
    "<a href=\"https://colab.research.google.com/github/wangyingsm/Python-Data-Science-Handbook/blob/master/notebooks/02.07-Fancy-Indexing.ipynb\"><img align=\"left\" src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open in Colab\" title=\"Open and Execute in Google Colaboratory\"></a>\n"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
